public class BinarySearchTree {

    static class TreeNode {
        public int val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(int val){
            this.val=val;
        }
    }

    public TreeNode root;

    public void insert(int val) {
        if (root==null) {
            root = new TreeNode(val);
            return;
        }
        TreeNode parent = null;
        TreeNode cur = root;
        while (cur!=null){
            if (val<cur.val){
                parent = cur;
                cur=cur.left;
            } else if(val>cur.val){
                parent = cur;
                cur=cur.right;
            } else {
                return;
            }
        }
        if (val<parent.val){
            parent.left = new TreeNode(val);
        }else {
            parent.right = new TreeNode(val);
        }
    }

    public TreeNode search(int val) {
        if (root==null){
            return null;
        }
        TreeNode cur = root;
        while (cur!=null){
            if (val>cur.val){
                cur=cur.right;
            }else if (val<cur.val){
                cur=cur.left;
            } else {
                return cur;
            }
        }
        return null;
    }

    public void remove(int key){
        if (root==null){
            return;
        }
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur!=null){
            if (key<cur.val){
                parent = cur;
                cur=cur.left;
            } else if(key>cur.val){
                parent = cur;
                cur=cur.right;
            } else {
                removeNode(parent,cur);
                return;
            }
        }
    }

    private void removeNode(TreeNode parent, TreeNode cur) {
        if (cur.left==null){
            if (cur==root){
                root=cur.right;
            }else if (cur==parent.left){
                parent.left=cur.right;
            }else {
                parent.right=cur.right;
            }
        }else if (cur.right==null){
            if (cur==root){
                root=cur.left;
            }else if (cur==parent.left){
                parent.left=cur.left;
            }else {
                parent.right=cur.left;
            }
        }else {
            TreeNode tp = cur;
            TreeNode t = cur.right;
            while (t.left!=null){
                tp=t;
                t=t.left;
            }
            cur.val=t.val;
            if (tp.left==t){
                tp.left=t.right;
            }else {
                tp.right=t.right;
            }
        }
    }

}
